package com.koicarp.university.graduate.auth.aop;

import com.alibaba.fastjson.JSON;
import com.koicarp.university.graduate.auth.constant.ModuleNameEnum;
import com.koicarp.university.graduate.auth.constant.OperateLogTypeEnum;
import com.koicarp.university.graduate.auth.service.UniversityAuthUser;
import com.koicarp.university.graudate.common.dao.LogOperateInfoDao;
import com.koicarp.university.graudate.common.entity.log.LogOperateInfo;
import com.koicarp.university.graduate.auth.annotation.OperLog;

import com.koicarp.university.graudate.common.utils.IpUtils;
import com.koicarp.university.graudate.common.utils.UniversityUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @auther liutao
 * @Date 2020-11-24 09:13:52
 */

@Aspect
@Component
public class OperateLogAop {

    @Autowired
    private LogOperateInfoDao logOperateInfoDao;

    @Pointcut("@annotation(com.koicarp.university.graduate.auth.annotation.OperLog)")
    public void operLogPointCut() {
    }

    @AfterReturning(value = "operLogPointCut()", returning = "keys")
    public void saveOperateLog(JoinPoint joinPoint,Object keys){
        try{
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            HttpServletRequest request = null;
            request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();//获取request
//            if (arguments != null){
////                for (Object obj : arguments){
////                    if (obj instanceof HttpServletRequest){
////                        request = (HttpServletRequest)obj;
////                        break;
////                    }
////                }
////            }
            if (request == null){
                return;
            }
            String url = request.getRequestURI();
            String userId = null;
            UniversityAuthUser principal = null;
            if(url.equals("/koicarp/oauth/token")){
                System.out.println(JSON.toJSONString(keys));
                principal = (UniversityAuthUser) keys;
            }else{
                principal = (UniversityAuthUser)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            }
            userId = principal.getUserId();
            String ip = IpUtils.getRealIP(request);
            Class[] argTypes = new Class[arguments.length];
            for (int i = 0; i < arguments.length;i++){
                argTypes[i] = arguments[i].getClass();
            }
            Class targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();
            ModuleNameEnum moduleName = null;
            OperateLogTypeEnum operationLogType = null;
            String des = null;
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length && compare(argTypes,clazzs)) {
                        moduleName = method.getAnnotation(OperLog.class).moduleName();
                        operationLogType = method.getAnnotation(OperLog.class).type();
                        des = method.getAnnotation(OperLog.class).operDesc();
                        break;
                    }
                }
            }
            if (UniversityUtil.isNotNull(moduleName) && UniversityUtil.isNotNull(operationLogType)){
                LogOperateInfo log = new LogOperateInfo();
                // 请求的参数
                Map<String, String> rtnMap = converMap(request.getParameterMap());
                // 将参数所在的数组转换成json
                String params = JSON.toJSONString(rtnMap);
                log.setOperModul(moduleName.getValue());
                log.setOperType(operationLogType.getValue()+"");
                log.setCreateTime(new Date());
                log.setOperDesc(des);
                log.setOperRequParam(params);
                log.setOperRespParam(JSON.toJSONString(keys));
                log.setUserIp(ip);
                log.setOperUri(url);
                log.setUserId(userId);
                this.logOperateInfoDao.insert(log);
            }
        } catch (Exception e){
            e.printStackTrace();
        }

    }


    private boolean compare(Class[] arr1,Class[] arr2){
        int length1 = arr1 == null ? 0: arr1.length;
        int length2 = arr2 == null ? 0: arr2.length;
        if (length1 != length2){
            return false;
        }
        if (length1 == 0 && length2 == 0){
            return true;
        }
        for (int i = 0;i < arr1.length;i++){
            if (arr1[i] != arr2[i] && arr1[i].isAssignableFrom(arr2[i])){
                return false;
            }
        }
        return true;
    }
    /**
     * 转换request 请求参数
     *
     * @param paramMap request获取的参数数组
     */
    public Map<String, String> converMap(Map<String, String[]> paramMap) {
        Map<String, String> rtnMap = new HashMap<String, String>();
        for (String key : paramMap.keySet()) {
            rtnMap.put(key, paramMap.get(key)[0]);
        }
        return rtnMap;
    }
}
